﻿using AutoMapper;
using Entity;
using Global;
using Global.ExtensionMethods;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using MysqlEFConfig;
using System.Data;

namespace ProdService
{
    public class BaseService
    {
        protected readonly static MapperConfiguration config;
        protected DbContext dbContext;
        protected HttpContext httpContext;
        static BaseService()
        {
            config = new MapperConfiguration(MapConfig.get());
        }

        public BaseService(DbContext dbContext,
            IHttpContextAccessor accessor = null)
        {
            this.dbContext = dbContext;
            DatabaseFacade db = this.dbContext.Database;
            if (db.CurrentTransaction == null)
            {
                db.BeginTransaction(IsolationLevel.ReadCommitted);
            }//else nothing

            httpContext = accessor?.HttpContext;
        }

        protected IMapper mapper
        {
            get { return config.CreateMapper(); }
        }

        protected User GetCurrentUser()
        {
            string key = Global.Const.CookieName.UserId;

            httpContext.Request.Cookies.TryGetValue(
                key, out string userIdentity);

            if (string.IsNullOrEmpty(userIdentity))
            {
                return null;
            }

            try
            {
                int userId = Convert.ToInt32(userIdentity);
                if (userId < 0) 
                {
                    return null;
                }

                string password = Global.Const.CookieName.Password;

                httpContext.Request.Cookies.TryGetValue(
                password, out string encryptInfo);

                if (string.IsNullOrEmpty(encryptInfo))
                {
                    string message = string.Format("cookie for {0}={1} has no encryption.", key, userId);
                    throw new Exception(message);
                }
                User user = dbContext.Set<User>().Find(userId);
                if (user == null) 
                {
                    string message = string.Format("cookie for user：{0} has doesn't exist.", userId);
                    throw new Exception(message);
                }
                if (user.Password.Md5Encypt() != encryptInfo)
                {
                    throw new Exception(string.Format(
                        "cookie for {0}={1} has wrong encryption：{2}.",
                        key, userId, encryptInfo));
                }
                return user;
            }
            catch (Exception)
            {
                throw;
            }
            return null;
        }

        /// <summary>
        /// 获取当前用户的角色
        /// </summary>
        /// <returns>null：未登录用户</returns>
        protected IList<Role> GetCurrentRoles()
        {
            User user = GetCurrentUser();
            if (user == null)
            {
                return null;
            }
            IList<Role> roles = new List<Role>();
            if (user.Contact != null)
            {
                roles.Add(Role.Contact);
            }

            return roles;
        }

        public bool HasRole(Role role)
        {
            User user = GetCurrentUser();
            
            if (user == null) //必须预先被截断
            {
                return false;
            }
            switch (role)
            {
                case Role.Logon:
                    return user != null;  //此时必然是true
                case Role.Contact:
                    return user.Contact != null;
                default:
                    throw new NotImplementedException($"{role}的检测尚未实现");
            }
        }

        protected void CurrentUserShouldBe(int userId)
        {
            int currentUserId = GetCurrentUser().Id;
            if (currentUserId != userId)
            {
                throw new Exception(
                    $"当前用户（id={currentUserId}）不是用户（id={userId}），不应具有相应权限");
            }
        }
    }
}